package top.nana7mi.headshot.event;

import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.WorldClient;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.block.model.IBakedModel;
import net.minecraft.client.renderer.culling.Frustum;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.texture.TextureMap;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.client.resources.I18n;
import net.minecraft.entity.*;
import net.minecraft.init.Items;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.text.TextFormatting;
import net.minecraft.world.World;
import net.minecraftforge.client.event.RenderWorldLastEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.relauncher.ReflectionHelper;
import org.lwjgl.opengl.GL11;
import top.nana7mi.headshot.Headshot;
import top.nana7mi.headshot.config.HeadShotConfig;

import java.awt.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.Stack;

public class RenderEventHandlerBak {

    List<EntityLivingBase> renderedEntities = new ArrayList<>();

    @SubscribeEvent
    public void onRenderWorldLast(RenderWorldLastEvent event) {
        Minecraft mc = Minecraft.getMinecraft();

//        if ((!HeadShotConfig.renderInF1 && !Minecraft.isGuiEnabled()) || !HeadShotConfig.draw)
//            return;

        if (!Minecraft.isGuiEnabled()){
            return;
        }

        Entity cameraEntity = mc.getRenderViewEntity();
        BlockPos renderingVector = cameraEntity.getPosition();

        Frustum frustum = new Frustum();
        float partialTicks = event.getPartialTicks();
        double viewX = cameraEntity.lastTickPosX + (cameraEntity.posX - cameraEntity.lastTickPosX) * partialTicks;
        double viewY = cameraEntity.lastTickPosY + (cameraEntity.posY - cameraEntity.lastTickPosY) * partialTicks;
        double viewZ = cameraEntity.lastTickPosZ + (cameraEntity.posZ - cameraEntity.lastTickPosZ) * partialTicks;
        frustum.setPosition(viewX, viewY, viewZ);

//        if (HeadShotConfig.showOnlyFocused) {
//            Entity focused = getEntityLookedAt((Entity)mc.player);
//            if (focused != null && focused instanceof EntityLivingBase && focused.isEntityAlive())
//                renderHealthBar((EntityLivingBase)focused, partialTicks, cameraEntity);
//        } else {
//            WorldClient client = mc.world;
//            Set<Entity> entities = (Set<Entity>) ReflectionHelper.getPrivateValue(WorldClient.class, client, new String[] { "entityList", "field_73032_d", "J" });
//            for (Entity entity : entities) {
//                if (entity != null && entity instanceof EntityLivingBase && entity != mc.player && entity.isInRangeToRender3d(renderingVector.getX(), renderingVector.getY(), renderingVector.getZ()) && (entity.ignoreFrustumCheck || frustum.isBoundingBoxInFrustum(entity.getEntityBoundingBox())) && entity.isEntityAlive() && entity.getRecursivePassengers().isEmpty())
//                    renderHealthBar((EntityLivingBase)entity, partialTicks, cameraEntity);
//            }
//        }

        WorldClient client = mc.world;
        Set<Entity> entities = (Set<Entity>) ReflectionHelper.getPrivateValue(WorldClient.class, client, new String[] { "entityList", "field_73032_d", "J" });
        for (Entity entity : entities) {

            if (entity != null && entity instanceof EntityLivingBase && entity != mc.player && entity.isInRangeToRender3d(renderingVector.getX(), renderingVector.getY(), renderingVector.getZ()) && (entity.ignoreFrustumCheck || frustum.isBoundingBoxInFrustum(entity.getEntityBoundingBox())) && entity.isEntityAlive() && entity.getRecursivePassengers().isEmpty())
                renderHealthBar((EntityLivingBase)entity, partialTicks, cameraEntity);

//            if (entity != null && entity instanceof EntityLivingBase && entity != mc.player && entity.isInRangeToRender3d(renderingVector.getX(), renderingVector.getY(), renderingVector.getZ()) && (entity.ignoreFrustumCheck || frustum.isBoundingBoxInFrustum(entity.getEntityBoundingBox())) && entity.getRecursivePassengers().isEmpty()) {
//                renderHeadShotIcon((EntityLivingBase) entity, partialTicks, cameraEntity);
//            }

        }
    }

    private static final ResourceLocation HEADSHOT_PNG = new ResourceLocation(Headshot.MOD_ID, "textures/gui/headshot.png");

    public void renderHeadShotIcon(EntityLivingBase passedEntity, float partialTicks, Entity viewPoint){

    }

//    private void renderIcon(int vertexX, int vertexY, ItemStack stack, int intU, int intV) {
//        try {
//
//            IBakedModel iBakedModel = Minecraft.getMinecraft().getRenderItem().getItemModelMesher().getItemModel(stack);
//            TextureAtlasSprite textureAtlasSprite = Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite(iBakedModel.getParticleTexture().getIconName());
//            Minecraft.getMinecraft().getTextureManager().bindTexture(TextureMap.LOCATION_BLOCKS_TEXTURE);
//
//            Tessellator tessellator = Tessellator.getInstance();
//            BufferBuilder buffer = tessellator.getBuffer();
//
//            buffer.begin(7, DefaultVertexFormats.POSITION_TEX);
//            buffer.pos(vertexX, (vertexY + intV), 0.0D).tex(textureAtlasSprite.getMinU(), textureAtlasSprite.getMaxV()).endVertex();
//            buffer.pos((vertexX + intU), (vertexY + intV), 0.0D).tex(textureAtlasSprite.getMaxU(), textureAtlasSprite.getMaxV()).endVertex();
//            buffer.pos((vertexX + intU), vertexY, 0.0D).tex(textureAtlasSprite.getMaxU(), textureAtlasSprite.getMinV()).endVertex();
//            buffer.pos(vertexX, vertexY, 0.0D).tex(textureAtlasSprite.getMinU(), textureAtlasSprite.getMinV()).endVertex();
//            tessellator.draw();
//        } catch (Exception exception) {
//
//        }
//    }

    public void renderHealthBar(EntityLivingBase passedEntity, float partialTicks, Entity viewPoint) {
        Stack<EntityLivingBase> ridingStack = new Stack<>();
        EntityLivingBase entity = passedEntity;

        ridingStack.push(entity);
        while (entity.getRidingEntity() != null && entity.getRidingEntity() instanceof EntityLivingBase) {
            entity = (EntityLivingBase)entity.getRidingEntity();
            ridingStack.push(entity);
        }

        Minecraft mc = Minecraft.getMinecraft();
        float pastTranslate = 0.0F;
        while (!ridingStack.isEmpty()) {
            entity = ridingStack.pop();
            boolean boss = !entity.isNonBoss();
            String entityID = EntityList.getEntityString((Entity)entity);

            if (HeadShotConfig.blacklist.contains(entityID))
                continue;
            float distance = passedEntity.getDistance(viewPoint);
            if (distance > HeadShotConfig.maxDistance || !passedEntity.canEntityBeSeen(viewPoint) || entity.isInvisible())
                continue;
            if (!HeadShotConfig.showOnBosses && !boss)
                continue;
            if (!HeadShotConfig.showOnPlayers && entity instanceof net.minecraft.entity.player.EntityPlayer)
                continue;

            double x = passedEntity.lastTickPosX + (passedEntity.posX - passedEntity.lastTickPosX) * partialTicks;
            double y = passedEntity.lastTickPosY + (passedEntity.posY - passedEntity.lastTickPosY) * partialTicks;
            double z = passedEntity.lastTickPosZ + (passedEntity.posZ - passedEntity.lastTickPosZ) * partialTicks;
            float scale = 0.026666673F;
            float maxHealth = entity.getMaxHealth();
            float health = Math.min(maxHealth, entity.getHealth());
            if (maxHealth <= 0.0F)
                continue;
            float percent = (int)(health / maxHealth * 100.0F);
            RenderManager renderManager = Minecraft.getMinecraft().getRenderManager();

            GlStateManager.pushMatrix();

            GlStateManager.translate((float)(x - renderManager.viewerPosX), (float)(y - renderManager.viewerPosY + passedEntity.height + HeadShotConfig.heightAbove), (float)(z - renderManager.viewerPosZ));
            GL11.glNormal3f(0.0F, 1.0F, 0.0F);
            GlStateManager.rotate(-renderManager.playerViewY, 0.0F, 1.0F, 0.0F);
            GlStateManager.rotate(renderManager.playerViewX, 1.0F, 0.0F, 0.0F);
            GlStateManager.scale(-scale, -scale, scale);
            boolean lighting = GL11.glGetBoolean(2896);
            GlStateManager.disableLighting();
            GlStateManager.depthMask(false);
            GlStateManager.disableDepth();
            GlStateManager.disableTexture2D();
            GlStateManager.enableBlend();
            GlStateManager.blendFunc(770, 771);
            Tessellator tessellator = Tessellator.getInstance();
            BufferBuilder buffer = tessellator.getBuffer();
            float padding = HeadShotConfig.backgroundPadding;
            int bgHeight = HeadShotConfig.backgroundHeight;
            int barHeight = HeadShotConfig.barHeight;
            float size = HeadShotConfig.plateSize;
            int r = 0;
            int g = 255;
            int b = 0;
            ItemStack stack = null;
            if (entity instanceof net.minecraft.entity.monster.IMob) {
                r = 255;
                g = 0;
                EnumCreatureAttribute attr = entity.getCreatureAttribute();
                switch (attr) {
                    case ARTHROPOD:
                        stack = new ItemStack(Items.SPIDER_EYE);
                        break;
                    case UNDEAD:
                        stack = new ItemStack(Items.ROTTEN_FLESH);
                        break;
                    default:
                        stack = new ItemStack(Items.SKULL, 1, 4);
                        break;
                }
            }
            if (boss) {
                stack = new ItemStack(Items.SKULL);
                size = HeadShotConfig.plateSizeBoss;
                r = 128;
                g = 0;
                b = 128;
            }
            int armor = entity.getTotalArmorValue();
            boolean useHue = !HeadShotConfig.colorByType;
            if (useHue) {
                float hue = Math.max(0.0F, health / maxHealth / 3.0F - 0.07F);
                Color color = Color.getHSBColor(hue, 1.0F, 1.0F);
                r = color.getRed();
                g = color.getGreen();
                b = color.getBlue();
            }
            GlStateManager.translate(0.0F, pastTranslate, 0.0F);
            float s = 0.5F;
            String name = I18n.format(entity.getDisplayName().getFormattedText(), new Object[0]);
            if (entity instanceof EntityLiving && ((EntityLiving)entity).hasCustomName()) {
                name = TextFormatting.ITALIC + ((EntityLiving)entity).getCustomNameTag();
            } else if (entity instanceof net.minecraft.entity.passive.EntityVillager) {
                name = I18n.format("entity.Villager.name", new Object[0]);
            }
            float namel = mc.fontRenderer.getStringWidth(name) * s;
            if (namel + 20.0F > size * 2.0F)
                size = namel / 2.0F + 10.0F;
            float healthSize = size * health / maxHealth;
            if (HeadShotConfig.drawBackground) {
                buffer.begin(7, DefaultVertexFormats.POSITION_COLOR);
                buffer.pos((-size - padding), -bgHeight, 0.0D).color(0, 0, 0, 64).endVertex();
                buffer.pos((-size - padding), (barHeight + padding), 0.0D).color(0, 0, 0, 64).endVertex();
                buffer.pos((size + padding), (barHeight + padding), 0.0D).color(0, 0, 0, 64).endVertex();
                buffer.pos((size + padding), -bgHeight, 0.0D).color(0, 0, 0, 64).endVertex();
                tessellator.draw();
            }
            buffer.begin(7, DefaultVertexFormats.POSITION_COLOR);
            buffer.pos(-size, 0.0D, 0.0D).color(127, 127, 127, 127).endVertex();
            buffer.pos(-size, barHeight, 0.0D).color(127, 127, 127, 127).endVertex();
            buffer.pos(size, barHeight, 0.0D).color(127, 127, 127, 127).endVertex();
            buffer.pos(size, 0.0D, 0.0D).color(127, 127, 127, 127).endVertex();
            tessellator.draw();
            buffer.begin(7, DefaultVertexFormats.POSITION_COLOR);
            buffer.pos(-size, 0.0D, 0.0D).color(r, g, b, 127).endVertex();
            buffer.pos(-size, barHeight, 0.0D).color(r, g, b, 127).endVertex();
            buffer.pos((healthSize * 2.0F - size), barHeight, 0.0D).color(r, g, b, 127).endVertex();
            buffer.pos((healthSize * 2.0F - size), 0.0D, 0.0D).color(r, g, b, 127).endVertex();
            tessellator.draw();
            GlStateManager.enableTexture2D();

            GlStateManager.pushMatrix();

            GlStateManager.translate(-size, -4.5F, 0.0F);
            GlStateManager.scale(s, s, s);
            mc.fontRenderer.drawString(name, 0, 0, 16777215);

            GlStateManager.pushMatrix();

            float s1 = 0.75F;
            GlStateManager.scale(s1, s1, s1);
            int h = HeadShotConfig.hpTextHeight;
            String maxHpStr = TextFormatting.BOLD + "" + (Math.round(maxHealth * 100.0D) / 100.0D);
            String hpStr = "" + (Math.round(health * 100.0D) / 100.0D);
            String percStr = (int)percent + "%";
            if (maxHpStr.endsWith(".0"))
                maxHpStr = maxHpStr.substring(0, maxHpStr.length() - 2);
            if (hpStr.endsWith(".0"))
                hpStr = hpStr.substring(0, hpStr.length() - 2);
            if (HeadShotConfig.showCurrentHP)
                mc.fontRenderer.drawString(hpStr, 2, h, 16777215);
            if (HeadShotConfig.showMaxHP)
                mc.fontRenderer.drawString(maxHpStr, (int)(size / s * s1 * 2.0F) - 2 - mc.fontRenderer.getStringWidth(maxHpStr), h, 16777215);
            if (HeadShotConfig.showPercentage)
                mc.fontRenderer.drawString(percStr, (int)(size / s * s1) - mc.fontRenderer.getStringWidth(percStr) / 2, h, -1);
            if (HeadShotConfig.enableDebugInfo && mc.gameSettings.showDebugInfo)
                mc.fontRenderer.drawString("ID: \"" + entityID + "\"", 0, h + 16, -1);

            GlStateManager.popMatrix();

            GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
            int off = 0;
            s1 = 0.5F;
            GlStateManager.scale(s1, s1, s1);
            GlStateManager.translate(size / s * s1 * 2.0F - 16.0F, 0.0F, 0.0F);
            mc.renderEngine.bindTexture(TextureMap.LOCATION_BLOCKS_TEXTURE);
            if (stack != null && HeadShotConfig.showAttributes) {
                renderIcon(off, 0, stack, 16, 16);
                off -= 16;
            }
            if (armor > 0 && HeadShotConfig.showArmor) {
                int ironArmor = armor % 5;
                int diamondArmor = armor / 5;
                if (!HeadShotConfig.groupArmor) {
                    ironArmor = armor;
                    diamondArmor = 0;
                }
                stack = new ItemStack((Item)Items.IRON_CHESTPLATE);
                int i;
                for (i = 0; i < ironArmor; i++) {
                    renderIcon(off, 0, stack, 16, 16);
                    off -= 4;
                }
                stack = new ItemStack((Item)Items.DIAMOND_CHESTPLATE);
                for (i = 0; i < diamondArmor; i++) {
                    renderIcon(off, 0, stack, 16, 16);
                    off -= 4;
                }
            }
            GlStateManager.popMatrix();
            GlStateManager.disableBlend();
            GlStateManager.enableDepth();
            GlStateManager.depthMask(true);
            if (lighting)
                GlStateManager.enableLighting();
            GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
            GlStateManager.popMatrix();
            pastTranslate -= (bgHeight + barHeight) + padding;
        }
    }

    private void renderIcon(int vertexX, int vertexY, ItemStack stack, int intU, int intV) {
        try {

            IBakedModel iBakedModel = Minecraft.getMinecraft().getRenderItem().getItemModelMesher().getItemModel(stack);
            TextureAtlasSprite textureAtlasSprite = Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite(iBakedModel.getParticleTexture().getIconName());
            Minecraft.getMinecraft().getTextureManager().bindTexture(TextureMap.LOCATION_BLOCKS_TEXTURE);

            Tessellator tessellator = Tessellator.getInstance();
            BufferBuilder buffer = tessellator.getBuffer();

            buffer.begin(7, DefaultVertexFormats.POSITION_TEX);
            buffer.pos(vertexX, (vertexY + intV), 0.0D).tex(textureAtlasSprite.getMinU(), textureAtlasSprite.getMaxV()).endVertex();
            buffer.pos((vertexX + intU), (vertexY + intV), 0.0D).tex(textureAtlasSprite.getMaxU(), textureAtlasSprite.getMaxV()).endVertex();
            buffer.pos((vertexX + intU), vertexY, 0.0D).tex(textureAtlasSprite.getMaxU(), textureAtlasSprite.getMinV()).endVertex();
            buffer.pos(vertexX, vertexY, 0.0D).tex(textureAtlasSprite.getMinU(), textureAtlasSprite.getMinV()).endVertex();
            tessellator.draw();
        } catch (Exception exception) {

        }
    }

    public static Entity getEntityLookedAt(Entity e) {
        Entity foundEntity = null;
        double finalDistance = 32.0D;
        double distance = 32.0D;
        RayTraceResult pos = raycast(e, 32.0D);
        Vec3d positionVector = e.getPositionVector();
        if (e instanceof net.minecraft.entity.player.EntityPlayer)
            positionVector = positionVector.addVector(0.0D, e.getEyeHeight(), 0.0D);
        if (pos != null)
            distance = pos.hitVec.distanceTo(positionVector);
        Vec3d lookVector = e.	getLookVec();
        Vec3d reachVector = positionVector.addVector(lookVector.x * 32.0D, lookVector.y * 32.0D, lookVector.z * 32.0D);
        Entity lookedEntity = null;
        List<Entity> entitiesInBoundingBox = e.getEntityWorld().getEntitiesWithinAABBExcludingEntity(e, e.getEntityBoundingBox().grow(lookVector.x * 32.0D, lookVector.y * 32.0D, lookVector.z * 32.0D).expand(1.0D, 1.0D, 1.0D));
        double minDistance = distance;
        for (Entity entity : entitiesInBoundingBox) {
            if (entity.canBeCollidedWith()) {
                float collisionBorderSize = entity.getCollisionBorderSize();
                AxisAlignedBB hitbox = entity.getEntityBoundingBox().expand(collisionBorderSize, collisionBorderSize, collisionBorderSize);
                RayTraceResult interceptPosition = hitbox.calculateIntercept(positionVector, reachVector);
                if (hitbox.contains(positionVector)) {
                    if (0.0D < minDistance || minDistance == 0.0D) {
                        lookedEntity = entity;
                        minDistance = 0.0D;
                    }
                } else if (interceptPosition != null) {
                    double distanceToEntity = positionVector.distanceTo(interceptPosition.hitVec);
                    if (distanceToEntity < minDistance || minDistance == 0.0D) {
                        lookedEntity = entity;
                        minDistance = distanceToEntity;
                    }
                }
            }
            if (lookedEntity != null && (minDistance < distance || pos == null))
                foundEntity = lookedEntity;
        }
        return foundEntity;
    }

    public static RayTraceResult raycast(Entity e, double len) {
        Vec3d vec = new Vec3d(e.posX, e.posY, e.posZ);
        if (e instanceof net.minecraft.entity.player.EntityPlayer)
            vec = vec.add(new Vec3d(0.0D, e.getEyeHeight(), 0.0D));
        Vec3d look = e.getLookVec();
        if (look == null)
            return null;
        return raycast(e.getEntityWorld(), vec, look, len);
    }

    public static RayTraceResult raycast(World world, Vec3d origin, Vec3d ray, double len) {
        Vec3d end = origin.add(ray.normalize().scale(len));
        RayTraceResult pos = world.rayTraceBlocks(origin, end);
        return pos;
    }

}
